package io.polly.thread;

import com.google.common.collect.Lists;
import io.polly.common.config.DynamicExecutorProperties;
import io.polly.thread.exception.DynamicExecutorException;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ldz
 * @version V1.0
 * @title: DynamicExecutorRegistry
 * @description: 管理所有动态池
 * @date: 2022/3/22 10:25
 */
@Slf4j
public class DynamicExecutorRegistry implements InitializingBean {

    @Resource
    private static DynamicExecutorProperties dynamicExecutorProperties;

    private static final Map<String, DynamicExecutor> DYNAMIC_EXECUTOR_MAP = new ConcurrentHashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {

        if (CollectionUtils.isEmpty(dynamicExecutorProperties.getExecutors())) {
            return;
        }

        dynamicExecutorProperties.getExecutors().forEach(dep -> {
            val executor = DynamicExecutorBuilder.newBuilder()
                    .corePoolSize(dep.getCorePoolSize())
                    .maximumPoolSize(dep.getMaximumPoolSize())
                    .keepAliveTime(dep.getKeepAliveTime())
                    .workQueue(dep.getQueueType(), dep.getQueueCapacity(), dep.isFair())
                    .rejectedExecutionHandler(dep.getRejectedHandlerType())
                    .threadFactory(dep.getExecutorNamePrefix())
                    .allowCoreThreadTimeOut(dep.isAllowCoreThreadTimeOut())
                    .threadPoolName(dep.getThreadPoolName())
                    .notifyItems(dep.getNotifyItems())
                    .buildDynamicExecutor();
            register(executor, "configuration");
        });
    }

    public static void register(DynamicExecutor executor, String source) {
        log.info("DynamicTp register, source: {}, executor: {}", source, executor.getThreadPoolName());
        DYNAMIC_EXECUTOR_MAP.put(executor.getThreadPoolName(), executor);
    }

    public static List<String> listRegisterExecutorName() {
        return Lists.newArrayList(DYNAMIC_EXECUTOR_MAP.keySet());
    }

    public static DynamicExecutor getExecutor(String name) {
        val executor= DYNAMIC_EXECUTOR_MAP.get(name);
        if (Objects.isNull(executor)) {
            log.error("Cannot find a specified DynamicExecutor, name: {}", name);
            throw new DynamicExecutorException("Cannot find a specified DynamicExecutor, name: " + name);
        }
        return executor;
    }
}
